import java.util.concurrent.PriorityBlockingQueue;

class MyTask implements Comparable<MyTask>{
    //要执行的任务内容
    private Runnable runnable;
    //任务在什么时间执行(使用毫秒级时间戳)
    private long time;

    public MyTask(Runnable runnable, long time) {
        this.runnable = runnable;
        this.time = time;
    }

    //获取任务当前的时间
    public long getTime(){
        return time;
    }

    //执行任务
    public void run(){
        runnable.run();
    }

    @Override
    public int compareTo(MyTask o) {
        //返回 小于 0，大于 0，等于 0
        //this 比 o 小 返回 <0
        //this 比 o 大 返回 >0
        //this 等于 o 返回 0
        //当前需要的是队首元素是时间最小的元素
        return (int) (this.time - o.time);
    }
}

//自主实现定时器
class MyTimer{
    //扫描线程
    private Thread t = null;

    //使用一个阻塞式的优先级队列，保存任务
    private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();

    //扫描线程实现
    public MyTimer(){
        t = new Thread(()->{
            while(true){
                //取出队首元素，查看队首元素是否到达时间
                //如果时间没到，将元素放回到任务队列中
                //如果时间到，将任务执行
                synchronized (this){
                    try {
                        //取出队首的元素
                        MyTask myTask = queue.take();
                        //获取当前的时间
                        long curTime = System.currentTimeMillis();
                        //当前的时间与之前设定的时间比较
                        if(curTime < myTask.getTime()){
                            //还没到点，不必执行
                            //假设现在10:00 取出的任务要 11:00 执行
                            queue.put(myTask);
                            //在 put 之后进行 wait 操作
                            synchronized (this){
                                //在获取后时间未到就阻塞等待，等待设定时间与当前时间之差的时长
                                this.wait(myTask.getTime() - curTime);
                            }
                        }else{
                            //表明时间到了，可以执行任务
                            myTask.run();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.start();
    }

    //指定两个参数
    //第一个是指定任务
    //第二个是指定在多少秒后执行
    public void schedule(Runnable runnable,long after){
        //这里要注意的是，after 是要在当前时间下，在等待多长时间，这里的时间戳获取当前的时间
        MyTask myTask = new MyTask(runnable,System.currentTimeMillis() + after);
        queue.put(myTask);
        //在插入元素后就进行唤醒
        synchronized (this){
            this.notify();
        }
    }
}
public class TimerCode {
    public static void main(String[] args) {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("任务1");
            }
        },1000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("任务2");
            }
        },2000);
    }
}
